<template>
  <!-- 自定义头部导航栏 -->
  <view class="header-navigation-bar">
    <image src="/static/logo-a.png" class="logo" mode="heightFix"></image>
    <view class="texts">
      <text>AI助手</text>
      <text>你的智能助手，帮助你获取知识</text>
    </view>
  </view>
  <!-- 幽灵元素 -->
  <view class="ghost"></view>
  <!-- 开场白 -->
  <view class="opening-speech fadeInUpElement" v-if="history.length <= 0">
    <view class="hi">你好，我是你的人工智能大模型，现在的我能够学习和理解人类的语言，进行多轮对话，回答问题，高效帮助人们获取信息、知识和灵感。快和我聊聊吧！如果你不确定从哪里开始，可以试试这样问我：</view>
    <view class="recommends">
      <view class="recommends-title">
        <image src="/static/wenwo.png" mode="heightFix"></image>
        <text>你可以这样问我</text>
      </view>
      <view class="recommends-content">
        <text class="recommends-item" v-for="(item, index) in recommendList" :key="index" @click="sendRecommend(item)">{{ item }}</text>
      </view>
    </view>
  </view>
  <!-- 消息内容区域 -->
  <view class="chat-area">
    <block v-for="(item, index) in history" :key="index">
      <view class="user-content" v-if="item.role === 'user'">
        <image src="/static/avatar.png" mode="widthFix"></image>
        <text>{{ item.content }}</text>
      </view>
      <view class="ai-content" v-if="item.role === 'assistant'">
        <view class="ai-thinking" v-if="item.isLoading">
          <view class="loading"></view>
          <text>AI正在思考中...</text>
        </view>
        <view class="ai-result" v-else>
          <!-- <view class="ai-result-content">
            有限公司和股份公司是两种不同的公司组织形式。有限公司是指股东对公司债务承担有限责任，即只承担其所认缴的出资额，不承担公司债务的个人或企业法人。而股份公司是指公司的股份可以自由买卖，股东对公司债务承担有限责任，即只承担其所持有的股份数额，不承担公司债务的个人或企业法人。
          </view> -->
          <text class="ai-result-content" :user-select="true">{{ item.content }}</text>
          <view class="ai-result-copy" v-if="item.isCopy">
            <image src="/static/fuzhi.png" mode="heightFix" @click="handleSetClipboardData(item.content)"></image>
          </view>
        </view>
      </view>
    </block>
  </view>
  <view class="aim" style="height: 100rpx; background-color: transparent;"></view>
  <!-- 消息发送区域 -->
  <view class="message-sending-area">
    <image src="/static/qingkong.png" mode="widthFix" @click="clearAll"></image>
    <input type="text" placeholder="你可以问我任何问题" v-model.trim="msg" @confirm="sendMsg" :disabled="isAnswer"/>
    <image src="/static/fasong.png" mode="widthFix" @click="sendMsg"></image>
  </view>
</template>

<script setup>
  import { getMenuButtonInfo, getWindowInfo } from '/utils/index.js'
  import { ref } from 'vue'
  const { top, right, height } = getMenuButtonInfo()
  const { screenWidth } = getWindowInfo()

  const msg = ref('')
  const assistantContent = ref('')
  const socketTask = ref(null)
  const text = ref([])
  const history = ref([])
  const isAnswer = ref(false)
  const recommendList = ref([
    '给我一份关于数字经济的毕业论文大纲',
    '帮我推荐几个送给女朋友的生日礼物',
    '帮我推荐几款好用的国货口红',
    '我要在夏天去云南旅游，有什么美食推荐吗',
    '帮我推荐几款流行的家装风格'
  ])
  async function sendMsg() {
    if(isAnswer.value) {
      uni.showToast({
        title: '等待AI回复完毕',
        icon: 'none'
      })
      return
    }
    if(!msg.value) {
      uni.showToast({
        title: '请输入询问内容',
        icon: 'none'
      })
      return
    }
    history.value.push({
      role: 'user',
      content: msg.value
    })
    history.value.push({
      role: 'assistant',
      content: '',
      isLoading: true,
      isCopy: false
    })
    isAnswer.value = true
    const { result } = await wx.cloud.callFunction({
      name: 'authUrl'
    })
    socketTask.value = uni.connectSocket({
      url: result.url,
      complete: () => {}
    })
    socketTask.value.onError(({errMsg}) => {
      uni.showToast({
        title: errMsg,
        icon: 'none'
      })
      msg.value = ''
      assistantContent.value = ''
      text.value = []
      isAnswer.value = false
    })
    socketTask.value.onOpen(() => {
      text.value.push({
        role: 'user',
        content: msg.value
      })
      msg.value = ''
      const data = {
        header: {
          app_id: result.appId
        },
        parameter: {
          chat: {
            domain: '4.0Ultra'
          }
        },
        payload: {
          message: {
            text: text.value
          }
        }
      }
      socketTask.value.send({
        data: JSON.stringify(data),
        success: () => { console.log('成功！') },
        fail: () => { console.log('失败！') }
      })
    })
    socketTask.value.onMessage(data => {
      history.value[history.value.length - 1].isLoading = false
      const textList = JSON.parse(data.data).payload.choices.text
      textList.forEach(value => {
        assistantContent.value += value.content.replace(/↵/g, '\n')
        history.value[history.value.length - 1].content += value.content.replace(/↵/g, '\n')
        uni.pageScrollTo({
          selector: '.aim'
        })
      })
      if(JSON.parse(data.data).header.status === 2) {
        isAnswer.value = false
        history.value[history.value.length - 1].isCopy = true
        text.value.push({
          role: 'assistant',
          content: assistantContent.value
        })
        socketTask.value.close({
          code: 1000,
          reason: 'AI回复完毕，正常关闭连接'
        })
      }
    })
  }
  function handleSetClipboardData(content) {
    uni.setClipboardData({
      data: content
    })
  }
  function clearAll() {
    if(isAnswer.value) {
      uni.showToast({
        title: '等待AI回复完毕',
        icon: 'none'
      })
      return
    }
    assistantContent.value = ''
    text.value = []
    history.value = []
    isAnswer.value = false
  }
  function sendRecommend(question) {
    msg.value = question
    sendMsg()
  }
</script>

<style>
  page {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    background-color: #f6f8fe;
  }

  view,
  image,
  text {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  .header-navigation-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 999;
    display: flex;
    align-items: center;
    padding-top: v-bind(top + 'px');
    padding-left: v-bind(screenWidth - right + 'px');
    background: linear-gradient(to bottom, #b3cffa, #f6f8fe);
  }

  .header-navigation-bar .logo {
    height: v-bind(height + 'px');
  }

  .header-navigation-bar .texts {
    display: flex;
    flex-direction: column;
    margin-left: v-bind(screenWidth - right + 'px');
  }

  .header-navigation-bar .texts text:nth-child(1) {
    font-size: 25rpx;
    font-weight: bold;
  }

  .header-navigation-bar .texts text:nth-child(2) {
    font-size: 20rpx;
    color: #798189;
  }

  .ghost {
    height: v-bind(top + height + 'px');
  }

  .opening-speech {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding-top: 50rpx;
    font-size: 30rpx;
  }

  .opening-speech .hi {
    padding: 10rpx;
    margin-bottom: 20rpx;
    width: 95%;
    background-color: white;
    border-radius: 10rpx;
  }

  .opening-speech .recommends {
    display: flex;
    flex-direction: column;
    width: 95%;
    background-color: white;
    border-radius: 10rpx;
  }

  .opening-speech .recommends .recommends-title {
    display: flex;
    align-items: center;
    padding: 10rpx;
  }

  .opening-speech .recommends .recommends-title image {
    height: 40rpx;
  }

  .opening-speech .recommends .recommends-title text {
    margin-left: 10rpx;
    font-weight: bold;
  }

  .opening-speech .recommends .recommends-content {
    display: flex;
    flex-direction: column;
  }

  .opening-speech .recommends .recommends-content .recommends-item {
    height: 100rpx;
    line-height: 100rpx;
    text-align: center;
    color: #6795ff;
    font-weight: bold;
  }

  .chat-area {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .chat-area .user-content {
    display: flex;
    margin: 30rpx 0;
    width: 95%;
  }

  .chat-area .user-content image {
    margin-right: 10rpx;
    width: 50rpx;
  }

  .chat-area .user-content text {
    flex: 1;
    color: #555d92;
  }

  .chat-area .ai-content {
    width: 95%;
    background-color: white;
    border-radius: 10rpx;
  }

  .chat-area .ai-content .ai-thinking {
    display: flex;
  }

  .chat-area .ai-content .ai-thinking .loading {
    margin-right: 10rpx;
    width: 50rpx;
    height: 50rpx;
    border: 5rpx solid #f3f3f3;
    /* 轨道颜色 */
    border-top: 5rpx solid #3498db;
    /* 旋转器颜色 */
    border-radius: 50%;
    animation: spin 2s linear infinite;
  }

  .chat-area .ai-content .ai-result {
    display: flex;
    flex-direction: column;
  }

  .chat-area .ai-content .ai-result .ai-result-content {
    display: flex;
    justify-content: flex-start;
    padding: 10rpx;
    border-bottom: 1px solid #f5f5f5;
  }

  .chat-area .ai-content .ai-result .ai-result-copy {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 10rpx;
  }

  .chat-area .ai-content .ai-result .ai-result-copy image {
    height: 30rpx;
  }

  .message-sending-area {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 999;
    display: flex;
    align-items: center;
    height: 100rpx;
    background-color: #f6f8fe;
    border-top: 1px solid #eee;
  }

  .message-sending-area image {
    margin: 0 20rpx;
    width: 50rpx;
  }

  .message-sending-area input {
    flex: 1;
    padding: 0 20rpx;
    height: 80%;
    background-color: white;
    border-radius: 10rpx;
  }

  @keyframes fadeInUp {
    from {
      transform: translateY(100%);
      opacity: 0;
    }

    to {
      transform: translateY(0);
      opacity: 1;
    }
  }

  .fadeInUpElement {
    animation-name: fadeInUp;
    animation-duration: 2s;
    animation-fill-mode: forwards;
  }

  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }

    100% {
      transform: rotate(360deg);
    }
  }
</style>